﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

using Supremacy.Types;

namespace Supremacy.Editor
{
    public class ParameterRoutedEventArgs<T> : RoutedEventArgs
    {
        private readonly T _parameter;

        public T Parameter
        {
            get { return _parameter; }
        }

        public ParameterRoutedEventArgs(RoutedEvent routedEvent, T parameter, object source)
            : base(routedEvent, source)
        {
            _parameter = parameter;
        }

        public ParameterRoutedEventArgs(RoutedEvent routedEvent, T parameter)
            : base(routedEvent)
        {
            _parameter = parameter;
        }
    }

    public class SelectionListView : ListView
    {
        public static readonly RoutedEvent SelectionActionRequestedEvent;
        public static readonly RoutedEvent PreviewSelectionActionRequestedEvent;

        #region Events
        public event EventHandler<ParameterRoutedEventArgs<object>> SelectionActionRequested
        {
            add { AddHandler(SelectionActionRequestedEvent, value); }
            remove { RemoveHandler(SelectionActionRequestedEvent, value); }
        }

        public event EventHandler<ParameterRoutedEventArgs<object>> PreviewSelectionActionRequested
        {
            add { AddHandler(PreviewSelectionActionRequestedEvent, value); }
            remove { RemoveHandler(PreviewSelectionActionRequestedEvent, value); }
        }
        #endregion

        #region Constructors
        static SelectionListView()
        {
            SelectionActionRequestedEvent = EventManager.RegisterRoutedEvent(
                "SelectionActionRequested",
                RoutingStrategy.Bubble,
                typeof(EventHandler<ParameterRoutedEventArgs<object>>),
                typeof(SelectionListView));

            PreviewSelectionActionRequestedEvent = EventManager.RegisterRoutedEvent(
                "PreviewSelectionActionRequested",
                RoutingStrategy.Tunnel,
                typeof(EventHandler<ParameterRoutedEventArgs<object>>),
                typeof(SelectionListView));

            SelectionModeProperty.OverrideMetadata(
                typeof(SelectionListView),
                new FrameworkPropertyMetadata(
                    SelectionMode.Single,
                    null,
                    CoerceSelectionMode));
        }
        #endregion

        #region Methods
        private static object CoerceSelectionMode(DependencyObject d, object baseValue)
        {
            return SelectionMode.Single;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if ((e.Key == Key.Enter) || (e.Key == Key.Return))
            {
                e.Handled = true;
                OnSelectionActionRequested();
            }
            else
            {
                base.OnKeyDown(e);
            }
        }

        protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
        {
            if (SelectedItem == null)
                return;

            DependencyObject source = e.OriginalSource as DependencyObject;
            UIElement container = ItemContainerGenerator.ContainerFromItem(SelectedItem) as UIElement;

            if ((source != null) && (container != null))
            {
                if ((source == container) || container.IsAncestorOf(source))
                {
                    e.Handled = true;
                    OnSelectionActionRequested();
                }
            }

            if (!e.Handled)
            {
                base.OnMouseDoubleClick(e);
            }
        }

        protected void OnSelectionActionRequested()
        {
            if (SelectedItem != null)
            {
                ParameterRoutedEventArgs<object> previewArgs = new ParameterRoutedEventArgs<object>(
                    PreviewSelectionActionRequestedEvent,
                    SelectedItem,
                    this);
                RaiseEvent(previewArgs);
                if (!previewArgs.Handled)
                {
                    RaiseEvent(new ParameterRoutedEventArgs<object>(
                        SelectionActionRequestedEvent,
                        SelectedItem,
                        this));
                }
            }
        }
        #endregion
    }
}